Skip to content

fix: correctness hardening — force-kill ownership check, sync cwd validation, lock/parse robustness#21

Merged
hefgi merged 1 commit into
mainfrom
claude/magical-einstein-7m4g40-hardening
Jun 11, 2026
Merged

fix: correctness hardening — force-kill ownership check, sync cwd validation, lock/parse robustness#21
hefgi merged 1 commit into
mainfrom
claude/magical-einstein-7m4g40-hardening

Conversation

@hefgi

@hefgi hefgi commented Jun 11, 2026

Copy link
Copy Markdown
Owner

Fixes #5
Fixes #8
Fixes #11

Three small correctness fixes, batched because each is a focused few-line change.

up --force: ownership check + graceful kill (#5)

The port sweep kill -9'd whatever lsof found listening on the session's recorded ports. A stale recorded port (rebooted machine, auto-bump elsewhere, unrelated app) meant killing an innocent process — while the project ships whose-pid specifically to stop agents doing the same thing.

  • each PID found by lsof is resolved via whose_pid::resolve scoped to this session; unowned listeners produce a warning ("kill it manually if intended") and are skipped
  • owned processes get SIGTERM with a 2s grace, then SIGKILL — no more immediate -9
  • the port sweep moved before the pid-file kill, so the pid files (the ownership evidence) still exist when ownership is checked

Behavior change to be aware of: --force no longer kills a manually-started, untracked process squatting the session's port — it warns instead. That is the point of #5, and the warning says exactly what to do.

ecluse sync: real worktree check instead of substring match (#8)

The cwd fallback accepted any directory whose path string contained the slug (/home/me/rapid-prototype matches slug api), plus any cwd under the repo root — including the main checkout, which sync would happily register as a session worktree. The fallback now requires the cwd to be inside a linked git worktree of this repo (is_inside_git_worktree + main_worktree_root == root, canonicalized) and uses that worktree's actual root.

Robustness batch (#11)

  • acquire_shared returned an empty state when state.lock was missing even though state.json existed with live sessions (ls said "no active sessions" while everything ran), and had an .expect panic path. It now creates the dir + lock file the same way acquire does and reads the real state.
  • ls no longer panics on a short/hand-edited started_at ([..16] byte-slice → .get(..16) fallback).
  • .env.ecluse had four divergent parsers (shell skipped comments, env/up --json didn't — comment lines leaked into JSON as keys, process.rs had a fourth variant). One shared env::parse_env_file now backs all of them.

Tests

  • acquire_shared_reads_state_when_lock_file_missing (fails on the old empty-state behavior)
  • parse_env_file_*: comments/blanks skipped, first-= split, missing-file empty, file order preserved
  • integration sync_rejects_repo_root_as_worktree

cargo fmt --check, cargo clippy -- -D warnings, cargo test (374 + 19) green.

https://claude.ai/code/session_017UcuvzMKHVfyBCcq8ipAko


Generated by Claude Code

…ck/parse robustness

Three small correctness fixes batched:

up --force (#5): the port sweep kill -9'd whatever lsof found listening
on the session's recorded ports — stale ports meant killing another
session's service or an unrelated app. PIDs now go through
whose_pid::resolve scoped to this session; unowned listeners get a
warning instead of a SIGKILL, owned ones get TERM with a 2s grace before
KILL. The sweep runs before the pid-file kill so ownership can still be
established from the pid files.

ecluse sync (#8): the cwd fallback accepted any directory whose path
contained the slug as a substring (and any cwd under the repo root,
including the main checkout). It now requires the cwd to be inside a
linked git worktree of this repo and uses that worktree's root.

robustness (#11): acquire_shared returned an empty state when state.lock
was missing even though state.json existed (and had a panic path); it now
recreates the lock file and reads the real state. ls no longer panics on
a short started_at. .env.ecluse parsing is unified in env::parse_env_file
— shell, env, up --json, and process spawning read the file identically,
and comment lines no longer leak into JSON output as keys.

Fixes #5
Fixes #8
Fixes #11

https://claude.ai/code/session_017UcuvzMKHVfyBCcq8ipAko
@hefgi hefgi merged commit 712417d into main Jun 11, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants